/*******************************************************************************
* Project: QSAR(Cute Software Architecture) 
*
* Copyright: Copyright(C) 2024 by YuetingBen, All Rights Reserved
*
* File name: DcmDsd.c
*
* Brief: ;
*
* Author: Yueting.Ben
*
* Module: DCMDSD in Dcm
*
* Revision:
* ------------------------------------------------------------------------------
* v0.1: 
* --Yueting.Ben, 2024-03-12 
* --Initial release

*******************************************************************************/

/** HEADER FILES **/
#include "DcmDsd.h"
#include "DcmCfg.h"


/** MACRO DEFINITION **/
#define DCM_PROGRESS_SID_CHECK ((Dcm_ProgressType)0x10u)
#define DCM_PROGRESS_SID_ACCESS_CHECK ((Dcm_ProgressType)0x11u)
#define DCM_PROGRESS_SUB_ID_CHECK ((Dcm_ProgressType)0x12u)
#define DCM_PROGRESS_SUB_ACCESS_CHECK ((Dcm_ProgressType)0x13u)
#define DCM_PROGRESS_REQUEST ((Dcm_ProgressType)0x14u)

/** TYPEDEF DEFINITION **/
typedef struct
{
    uint8 svcIdIndex;
    uint8 subIdIndex;
    Dcm_ProgressType progress;
    Dcm_MsgContextType msgContext;
    DcmDspSessionType* sessionPtr;
    DcmDspSecurityType* securityPtr;
    Dcm_ProcessorFncType processor;
}DcmDsd_InfoType;


/** LOCAL DATA DECLARATION **/
static DcmDsd_InfoType DcmDsdInfo;


/** GLOBAL DATA DECLARATION **/


/** LOCAL FUNCTION DECLARATION **/
Std_ReturnType DcmDsd_MainProcessor(
    Dcm_ExtendedOpStatusType OpStatus,
    PduInfoType* info,
    Dcm_SvcCfgType* svcTablePtr,
    Dcm_NegativeResponseCodeType* ErrorCode
);

/** GLOBAL FUNCTION DECLARATION **/


/** LOCAL DATA **/


/** GLOBAL DATA **/


/** LOCAL FUNCTION **/


/** GLOBAL FUNCTION **/
Std_ReturnType DcmDsd_MainProcessor(
    Dcm_ExtendedOpStatusType OpStatus,
    PduInfoType* info,
    Dcm_SvcCfgType* svcTablePtr,
    Dcm_NegativeResponseCodeType* ErrorCode
)
{
    Std_ReturnType retVal = E_NOT_OK;

    Dcm_SvcIdType svcIdIndex;
    uint8 subIdIndex;
    uint8 svcId;
    uint8 subId;
    Dcm_MsgContextType msgContext;
    Dcm_SvcCfgType* svcCfgPtr;
    static Dcm_ProgressType processorProgress = DCM_PROGRESS_INITIAL;
    
    Dcm_ExtendedOpStatusType opStatus;

    DcmDsd_InfoType* dsdInfoPtr = &DcmDsdInfo;
    
    svcId = info->SduDataPtr[DCM_SDU_SID_INDEX];
    subId = info->SduDataPtr[DCM_SDU_SUBID_INDEX];


    switch(dsdInfoPtr->progress)
    {
        case DCM_PROGRESS_INITIAL:
        {
            retVal = DCM_E_PENDING;
            dsdInfoPtr->progress = DCM_PROGRESS_SID_CHECK;
            break;
        }
        case DCM_PROGRESS_SID_CHECK:
        {
            /* Diagnostic service execution rights verification */
            *ErrorCode = DCM_E_SERVICENOTSUPPORTED;
            for(svcIdIndex = DCM_SVC_ID_FIRST; svcIdIndex < DCM_SVC_ID_MAX; svcIdIndex++)
            {
                /* Checks on service ID level */
                svcCfgPtr = (Dcm_SvcCfgType*)(&svcTablePtr[svcIdIndex]);
                if(svcId == svcCfgPtr->sid)
                {
                    dsdInfoPtr->svcIdIndex = svcIdIndex;

                    dsdInfoPtr->sessionPtr = (DcmDspSessionType*)&svcCfgPtr->sidTabSessionLevel;
                    dsdInfoPtr->securityPtr = (DcmDspSecurityType*)&svcCfgPtr->sidTabSecurityLevel;
                    dsdInfoPtr->processor = svcCfgPtr->processor;
                    dsdInfoPtr->progress = DCM_PROGRESS_SID_ACCESS_CHECK;

                    retVal = DCM_E_PENDING;
                    break;
                }
            }
            
            break;
        }
        case DCM_PROGRESS_SID_ACCESS_CHECK:
        {
            svcCfgPtr = (Dcm_SvcCfgType*)(&svcTablePtr[dsdInfoPtr->svcIdIndex]);
            retVal = DcmDsp_SessionCheck(dsdInfoPtr->sessionPtr);
            if(E_OK == retVal)
            {
                retVal = DcmDsp_SecurityCheck(dsdInfoPtr->securityPtr);
                if(E_OK == retVal)
                {
                    retVal = DCM_E_PENDING;
                    if(SET == svcCfgPtr->subFuncSupported)
                    {
                        dsdInfoPtr->progress = DCM_PROGRESS_SUB_ID_CHECK;

                    }
                    else
                    {
                        dsdInfoPtr->progress = DCM_PROGRESS_REQUEST;
                        processorProgress = DCM_PROGRESS_INITIAL;
                    }
                }
                else
                {
                    *ErrorCode = DCM_E_SECURITYACCESSDENIED;
                }
            }
            else
            {
                *ErrorCode = DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION;
            }   
            
            break;
        }
        case DCM_PROGRESS_SUB_ID_CHECK:
        {
            svcCfgPtr = (Dcm_SvcCfgType*)(&svcTablePtr[dsdInfoPtr->svcIdIndex]);
            *ErrorCode = DCM_E_SUBFUNCTION_NOTSUPPORTE;
            for(subIdIndex = DCM_SUB_FUNC_ID_FIRST_INDEX; subIdIndex < svcCfgPtr->subFuncMaxIndex; subIdIndex++)
            {
                if(subId == svcCfgPtr->subSvcCfgPtr[subIdIndex].subId)
                {
                    dsdInfoPtr->subIdIndex = subIdIndex;
                    dsdInfoPtr->sessionPtr = (DcmDspSessionType*)&svcCfgPtr->subSvcCfgPtr[subIdIndex].subServiceSessionLevel;
                    dsdInfoPtr->securityPtr = (DcmDspSecurityType*)&svcCfgPtr->subSvcCfgPtr[subIdIndex].subServiceSecurityLevel;
                    dsdInfoPtr->processor = svcCfgPtr->subSvcCfgPtr[subIdIndex].processor;
                    dsdInfoPtr->progress = DCM_PROGRESS_SUB_ACCESS_CHECK;

                    retVal = DCM_E_PENDING;
                    break;
                }
            }
            break;
        }
        case DCM_PROGRESS_SUB_ACCESS_CHECK:
        {
            retVal = DcmDsp_SessionCheck(dsdInfoPtr->sessionPtr);
            if(E_OK == retVal)
            {
                retVal = DcmDsp_SecurityCheck(dsdInfoPtr->securityPtr);
                if(E_OK == retVal)
                {
                    retVal = DCM_E_PENDING;
                    dsdInfoPtr->progress = DCM_PROGRESS_REQUEST;
                    processorProgress = DCM_PROGRESS_INITIAL;
                }
                else
                {
                    *ErrorCode = DCM_E_SECURITYACCESSDENIED;
                }
            }
            else
            {
                *ErrorCode = DCM_E_SUBFUNCTIONNOTSUPPORTEDINACTIVESESSION;
            }   
            
            break;
        }
        case DCM_PROGRESS_REQUEST:
        {
            if(DCM_NULL_PROCESSOR != dsdInfoPtr->processor)
            {
                dsdInfoPtr->msgContext.reqData = (Dcm_MsgType)(&info->SduDataPtr[1]);
                dsdInfoPtr->msgContext.resData = (Dcm_MsgType)(&info->SduDataPtr[1]);
                dsdInfoPtr->msgContext.progressPtr = &processorProgress;
                retVal = dsdInfoPtr->processor(opStatus, &(dsdInfoPtr->msgContext), ErrorCode);
            }
            
            break;
        }
    }
    
    if(E_OK == retVal)
    {
        info->SduDataPtr[DCM_SDU_SID_INDEX] += 0x40u; 
        info->SduLength = dsdInfoPtr->msgContext.resDataLen + 1u;
        dsdInfoPtr->progress = DCM_PROGRESS_INITIAL;
    }
    else if(E_NOT_OK == retVal)
    {
        dsdInfoPtr->progress = DCM_PROGRESS_INITIAL;
    }
    
    return(retVal);
}




